package cn.sdfykjyxgs.synclient.config;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.StreamProgress;
import cn.hutool.core.lang.Console;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.sdfykjyxgs.synclient.base.API;
import cn.sdfykjyxgs.synclient.base.HttpResult;
import cn.sdfykjyxgs.synclient.entity.FileSynConfig;
import cn.sdfykjyxgs.synclient.util.MyFileLogQuery;
import cn.sdfykjyxgs.syncommon.entity.FileChangeLog;
import cn.sdfykjyxgs.syncommon.socket.WebSocketMessage;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Map;

@Component
public class HttpTool {
    @Resource
    WebSocketServer webSocketServer;
    private static String serverIp;
    private static Long port;
    private static String downloadPath;

    public static void initSetting(FileSynConfig config) {
        serverIp = config.getIp();
        port = config.getPort();
        downloadPath = config.getLocalPath();
    }

    public HttpResult get(String url) {
        HttpResult result = get(url, null);
        return result;
    }

    public HttpResult get(String ip, Long port, String url) {
        this.serverIp = ip;
        this.port = port;
        HttpResult result = get(url, null);
        return result;
    }

    public HttpResult get(String url, Map<String, Object> params) {
        HttpResult httpResult = new HttpResult();
        //链式构建请求
        String requestUrl = "http://" + serverIp + ":" + port + url;
        try {
            String result = HttpRequest.get(requestUrl)
                    .header(Header.USER_AGENT, "")//头信息，多个头信息多次调用此方法即可
                    .form(params)//表单内容
                    .timeout(1000)//超时，毫秒
                    .execute().body();
            httpResult.setCode(200);
            httpResult.setData(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return httpResult;
    }

    public HttpResult synFile(String url, Long fileId) {
        HttpResult httpResult = get(API.QUERY_BY_ID + "?fileId=" + fileId);
        if (httpResult.getCode() == 200) {
            JSONObject entries = JSONUtil.parseObj(httpResult.getData().toString());
            String name = entries.getStr("name");
            String remark = entries.getStr("remark");
            String fileLatestTime = entries.getStr("fileLatestTime");
            String logic = entries.getStr("logic");
            Long fileType = entries.getLong("fileType");

            switch (logic) {
                case "MOVE":
                    File oldFile = FileUtil.file(downloadPath + "\\" + remark);
                    File newFile = FileUtil.file(downloadPath + "\\" + name);
                    if (oldFile.exists()) {
                        FileUtil.move(oldFile, newFile, true);
                        synFileInfo(fileId, newFile, fileLatestTime);
                    }
                    sendProgress(entries, 100L);
                    break;
                case "RENAMED":
                    File oldPath = new File(downloadPath + "\\" + remark);
                    File newFolder = new File(downloadPath+"\\"+ name);
                    boolean isRenamed = oldPath.renameTo(newFolder);
                    if (isRenamed) {
//                        System.out.println("文件夹重命名成功！");
                        synFileInfo(fileId, newFolder, fileLatestTime);
                        sendProgress(entries, 100L);
                    } else {
                        System.err.println("文件夹重命名失败！");
                    }
                    break;
                case "DELETE":
                    File deleteFile = FileUtil.file(downloadPath + "\\" + name);
                    FileUtil.clean(deleteFile);
                    if(deleteFile.exists()){
                        deleteFile.delete();
                    }
                    synFileInfo(fileId, null, fileLatestTime);
                    sendProgress(entries, 100L);
                    break;
                default:
                    String requestUrl = "http://" + serverIp + ":" + port + url + "?fileId=" + fileId;
                    //带进度显示的文件下载
                    File file = FileUtil.file(downloadPath + "\\" + name);
                    if (fileType == 0) {
                        if (!file.exists()) {
                            file.mkdir();
                        }
                        synFileInfo(fileId, file, fileLatestTime);
                        break;
                    }
                    final Long[] tempProgress = {0L};
                    HttpUtil.downloadFile(requestUrl, file, new StreamProgress() {
                        @Override
                        public void start() {
//                            Console.log("开始下载。。。。");
                        }

                        /**
                         * 进行中
                         *
                         * @param total        总大小，如果未知为 -1或者{@link Long#MAX_VALUE}
                         * @param progressSize 已经进行的大小
                         */
                        @Override
                        public void progress(long total, long progressSize) {
//                            Console.log("总大小：{} 已下载：{}", FileUtil.readableFileSize(total), FileUtil.readableFileSize(progressSize));
                            long l = BigDecimal.valueOf(progressSize).divide(BigDecimal.valueOf(total), 2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).longValue();

                            //发送进度消息
                            if (tempProgress[0] != l) {
                                tempProgress[0] = l;
                                MyFileLogQuery.list.forEach(item -> {
                                    if (item.getId().longValue() == fileId.longValue())
                                        item.setProgress(l);
                                });
                                sendProgress(entries, l);
                            }
                        }

                        @Override
                        public void finish() {
//                            Console.log("下载完成！");
                            //修改文件的最后跟新时间于服务端文件保持一致
                            synFileInfo(fileId, file, fileLatestTime);
                            sendProgress(entries, 100L);
                        }
                    });
            }

        }

        return new HttpResult<>(200);
    }

    public void synFileInfo(Long fileId, File file, String fileLatestTime) {
        //修改文件的最后跟新时间于服务端文件保持一致
        if (file != null) {
            DateTime parse = DateUtil.parse(fileLatestTime);
            file.setLastModified(parse.getTime());
        }
        //刷新文件的同步状态
        get(API.REFRESH_STATUS + "?fileId=" + fileId);
    }

    public void changeSpeed(FileSynConfig config){
        get(API.CHANGESPEED+"?maxRate=" + (config.getMaxRate() == null ? 0 : config.getMaxRate())
                +"&filterFormat="+config.getFilterFormat());
    }

    public void sendProgress(JSONObject entries, Long progress) {
        //发送进度消息
        ArrayList<FileChangeLog> logs = new ArrayList<>();
        FileChangeLog fileChangeLog = JSONUtil.toBean(entries, FileChangeLog.class);
        fileChangeLog.setProgress(progress);
        logs.add(fileChangeLog);
        WebSocketServer.sendMessage(new WebSocketMessage("", "10002", logs));
    }
}
